﻿using _220105BookSys.api.Tools;
using _220105BookSys.api.Tools.QueryParam;
using _220105BookSys.Dto.Book;
using _220105BookSys.IRepository;
using _220105BookSys.Model;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace _220105BookSys.api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BookController : ControllerBase
    {
        //private readonly ILogger logger;
        private readonly IBookRepository bookRepository;
        private readonly IBookTypeRepository bookTypeRepository;
        private readonly IMapper mapper;

        public BookController(IBookRepository bookRepository, IBookTypeRepository bookTypeRepository, IMapper mapper)
        {

            this.bookRepository = bookRepository;
            this.bookTypeRepository = bookTypeRepository;
            this.mapper = mapper;
        }

        #region Get
        ///Get All Book
        [HttpGet]
        public async Task<IActionResult> Get()
        {
            var result = await bookRepository.GetBooksAsync();
            return Ok(mapper.Map<List<BookDto>>(result));
        }

        /// <summary>
        /// Get By Paged
        /// </summary>
        /// <returns></returns>
        [HttpGet("Paged")]
        public async Task<IActionResult> GetPaged([FromQuery] Pagination pagination)
        {
            pagination.Total = await bookRepository.GetTotalAsync();
            if (pagination.Total <= 0)
            {
                return NoContent();
            }
            var result = await bookRepository.GetBooksAsync(pagination.PageIndex, pagination.PageSize);
            pagination.Data = mapper.Map<List<BookDto>>(result);

            return Ok(pagination);
        }

        /// <summary>
        /// Get By Query:ID/Name/Describe/BookTypeId
        /// </summary>
        /// <returns></returns>
        [HttpGet("Query")]
        public async Task<IActionResult> GetByQuery([FromQuery] BookQuery bookQuery)
        {
            var result = await bookRepository.GetBooksAsync();
            //判断各个选项是否为空，如果不为空，则执行对应的条件查询
            if (bookQuery.Id != null && bookQuery.Id.ToString() != "")
            {
                result = result.Where(b => b.Id.Equals(bookQuery.Id));
            }
            if (bookQuery.Name != null && bookQuery.Name != "")
            {
                result = result.Where(b => b.Name.Contains(bookQuery.Name));
            }
            if (bookQuery.Describe!=null&&bookQuery.Describe!="")
            {
                result = result.Where(b => b.Describe.Contains(bookQuery.Describe));
            }
            if (bookQuery.BookTypeId!=null)
            {
                result = result.Where(b => b.BookTypeId == bookQuery.BookTypeId);
            }
            return Ok(mapper.Map<List<BookDto>>(result.ToList()));
        }


        /// <summary>
        /// Get By Paged and Query
        /// </summary>
        /// <returns></returns>
        [HttpGet("QueryAndPaged")]
        public async Task<IActionResult> GetByQueryAndPaged([FromQuery] BookQuery bookQuery, [FromQuery] Pagination pagination)
        {
            var result = await bookRepository.GetBooksAsync();
            //判断各个选项是否为空，如果不为空，则执行对应的条件查询
            if (bookQuery.Id != null && bookQuery.Id.ToString() != "")
            {
                result = result.Where(b => b.Id.Equals(bookQuery.Id));
            }
            if (bookQuery.Name != null && bookQuery.Name != "")
            {
                result = result.Where(b => b.Name.Contains(bookQuery.Name));
            }
            if (bookQuery.Describe != null && bookQuery.Describe != "")
            {
                result = result.Where(b => b.Describe.Contains(bookQuery.Describe));
            }
            if (bookQuery.BookTypeId != null)
            {
                result = result.Where(b => b.BookTypeId == bookQuery.BookTypeId);
            }

            //手动分页
            pagination.Total = result.Count();/*执行Count方法时会执行IQueryable延迟查询*/
            if (pagination.Total <= 0)
            {
                return NoContent();
            }
            result = result.Skip((pagination.PageIndex - 1) * pagination.PageSize).Take(pagination.PageSize).ToList();
            pagination.Data = mapper.Map<List<BookDto>>(result);

            return Ok(pagination);
        }

        /// <summary>
        /// Get Single
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "GetSingle")]
        public async Task<IActionResult> GetSingle([FromRoute] Guid id)
        {
            var result = await bookRepository.GetBookAsync(id);
            if (result == null)
            {
                return NotFound("未找到指定对象！");
            }
            return Ok(mapper.Map<BookDto>(result));
        }

        #endregion

        #region Create
        /// <summary>
        /// Create
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Create([FromBody] BookDtoForCreatation BookDtoForCreatation)
        {

            var book = mapper.Map<Book>(BookDtoForCreatation);
            
            var result = await this.bookRepository.CreateAsync(book);
            if (result)
            {
                return CreatedAtRoute(nameof(GetSingle), new { id = book.Id }, mapper.Map<BookDto>(book));
            }
            else return BadRequest("服务器错误，添加失败！");
        }
        #endregion

        #region Update
        /// <summary>
        /// Update By HttpPut
        /// </summary>
        /// <returns></returns>
        [HttpPut("{BookId}")]
        public async Task<IActionResult> Update([FromRoute] Guid BookId, [FromBody] BookDtoForUpdate bookDtoForUpdate )
        {
            //1、先找到指定的对象，
            var targetBook = await bookRepository.GetBookAsync(BookId);
            if (targetBook == null||!await bookTypeRepository.IsExsitedAsync(bookDtoForUpdate.BookTypeId))
            {
                return NotFound("未找到指定对象！");
            }
            //2、再更新指定对象的指定更改了的数据
            targetBook.Name = bookDtoForUpdate.Name;
            targetBook.Describe = bookDtoForUpdate.Describe;
            targetBook.BookTypeId = bookDtoForUpdate.BookTypeId;
            //3、执行Update
            var result = await bookRepository.UpdateAsync(targetBook);
            if (result)
            {
                return Ok(targetBook);
            }
            else return BadRequest("服务器错误，修改失败！");

        }


        /// <summary>
        /// Update By HttpPatch 暂时不考虑使用HttpPatch，因为目前项目复杂度和操作要求简单，而且封装JsonPatchDocument麻烦
        /// </summary>
        /// <returns></returns>
        //[HttpPatch]
        //public async Task<IActionResult> UpdatePatch([FromRoute] Guid BookId, [FromBody] BookDtoForPutUpdate BookDtoForPutUpdate)
        //{
        //    //1、先找到指定的对象，
        //    var targetBook = await bookRepository.GetBookAsync(BookId);
        //    if (targetBook == null)
        //    {
        //        return NotFound("未找到指定对象！");
        //    }
        //    //2、再更新指定对象的指定更改了的数据
        //    targetBook.Name = BookDtoForPutUpdate.Name;
        //    //3、执行Update
        //    var result = await bookRepository.UpdateAsync(targetBook);
        //    if (result)
        //    {
        //        return Ok(targetBook);
        //    }
        //    else return BadRequest("服务器错误，修改失败！");

        //}
        #endregion

        #region Delete
        /// <summary>
        /// Create
        /// </summary>
        /// <returns></returns>
        [HttpDelete("{bookId}")]
        public async Task<IActionResult> Delete([FromRoute] Guid bookId)
        {

            //1、判断是否存在
            if (!await bookRepository.IsExsitedAsync(bookId))
            {
                return NotFound("未找到指定对象！");
            }
            //2、删除对象
            var result = await bookRepository.RealDeleteAsync(bookId);
            //return result ? NoContent() : BadRequest("服务器错误，删除失败！");
            if (result)
            {
                return NoContent();
            }
            return BadRequest("服务器错误，删除失败！");
        }
        #endregion

    }
}
